import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
from PIL import Image
from skimage import data
from math import floor, ceil
from skimage.feature import greycomatrix, greycoprops


def image_patch(img, sliding_window, h, w):
    patch = np.zeros((sliding_window, sliding_window, h, w), dtype=np.uint8)

    for i in range(h):
        for j in range(w):
            patch[..., i, j] = img[i: i + sliding_window, j: j + sliding_window]

    return patch


def cal_glcm(img, vmin=0, vmax=255, nbit=64, sliding_window=5, step=[2], angle=[0]):
    min, max = vmin, vmax
    h, w = img.shape

    bins = np.linspace(min, max + 1, nbit + 1)
    img1 = np.digitize(img, bins) - 1

    distance = floor(sliding_window / 2)
    img2 = cv.copyMakeBorder(img1, distance, distance, distance, distance, cv.BORDER_REPLICATE)
    patch = image_patch(img2, sliding_window, h, w)

    glcm = np.zeros((nbit, nbit, len(step), len(angle), h, w), dtype=np.uint8)
    for i in range(glcm.shape[2]):
        for j in range(glcm.shape[3]):
            glcm[..., i, j] = greycomatrix(patch[..., i, j], step, angle, levels=nbit)

    return glcm